home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-04 | 68.4 KB | 2,699 lines |
- ;
- ; EJEMPLOS DEL LENGUAJE CPP
- ;
-
- ; LECCION 1
- begin
- begine ""
- #include <stdio.h>
- #include <conio.h>
-
- void main (void)
- {
- puts ("Estas líneas están escritas por un programa C.");
- puts ("Por consiguiente, también están escritas por un programa C++.");
- puts ("Al ser el C++ una extensión del C, todo programa C es también programa C++.");
- getch ();
- }
- ende
- end
-
- ; LECCION 2
- begin
- begine " ORDENACION RAPIDA "
- /*
- En este programa se realiza la ordenación creciente de un vector de números
- en coma flotante por el método quicksort (ordenación rápida).
-
- La función principal general aleatoriamente 200 números de tipo float, los
- ordena llamando a la función quick_sort() y por último los visualiza.
-
- La ordenación rápida se basa en la idea de las particiones. El procedimiento
- general es seleccionar un valor pivote y entonces dividir el array en dos
- partes. En un lado todos los elementos mayores o iguales al valor de partición
- y en otro todos los elementos menores que el valor. Este proceso se repite
- en cada parte restante hasta que el array está ordenado.
-
- Este programa utiliza las siguientes mejoras del C++ respecto al C:
- - Nuevo estilo de comentario (//): // Quicksort (Ordenación rápida). Un ...
- - Nuevo flujo de salida estándar (cout): cout << "Memoria insuficiente.\n";
- - Funciones en línea (inline): inline void inicializar_numeros_aleatorios (void);
- - Nuevos operadores de gestión de memoria dinámica (new y delete): delete datos;
- - Conversión de tipo explícita mediante notación funcional: unsigned (time (NULL))
- - Parámetros por referencia en las funciones: operador &: void intercambiar (float& valor1, float& valor2);
- - Declaración en cualquier lugar: for (register int i = 0; ...
- */
-
- // Quicksort (Ordenación rápida). Un algoritmo desarrollado por C. A. R. Hoare
-
- #include <iostream.h> // cout, << sobrecargado
- #include <stdlib.h> // srad(), rand(), NULL
- #include <time.h> // time()
- #include <conio.h> // getch()
-
- // Inicializa el generador de números aleatorios.
- inline void inicializar_numeros_aleatorios (void)
- {
- srand (unsigned (time (NULL)));
- }
-
- // Devuelve un valor aleatorio entre 1 y num_max.
- inline unsigned aleatorio (unsigned num_max)
- {
- return (rand () % num_max + 1);
- }
-
- void main (void)
- {
- void quick_sort (float *punt_bajo, float *punt_alto);
- void visualizar_datos (float *dat, const int tam);
- float *datos;
- const int tamanio = 200;
- const unsigned num_aleat_max = 10000;
-
- if ((datos = new float[tamanio]) == 0)
- cout << "Memoria insuficiente.\n";
- else
- {
- inicializar_numeros_aleatorios ();
- for (register int i = 0; i < tamanio; i++)
- *(datos + i) = float (aleatorio (num_aleat_max)) / aleatorio (num_aleat_max);
- quick_sort (datos, datos + tamanio - 1);
- visualizar_datos (datos, tamanio);
- delete datos;
- }
- getch ();
- }
-
- void quick_sort (float *punt_bajo, float *punt_alto)
- {
- float *punt_pivote;
- float *particion (float *punt_bajo, float *punt_alto);
-
- if (punt_bajo < punt_alto)
- {
- punt_pivote = particion (punt_bajo, punt_alto);
- quick_sort (punt_bajo, punt_pivote - 1);
- quick_sort (punt_pivote, punt_alto);
- }
- }
-
- float *particion (float *punt_bajo, float *punt_alto)
- {
- void intercambiar (float& valor1, float& valor2);
- float pivote = *(punt_bajo + (punt_alto - punt_bajo) / 2);
-
- /*
- A la terminación de este bucle, el valor de todos los elementos a la
- izquierda del pivote serán menores que el valor del elemento del pivote,
- y todos los elementos a la derecha del pivote serán mayores que el valor
- del elemento del pivote.
- */
- while (punt_bajo <= punt_alto)
- {
- // Busca un valor en la parte baja del array mayor que el pivote
- while (*punt_bajo < pivote)
- punt_bajo++;
- // Busca un valor en la parte alta del array menor que el pivote
- while (*punt_alto > pivote)
- punt_alto--;
- if (punt_bajo <= punt_alto)
- intercambiar (*punt_bajo++, *punt_alto--);
- }
- return punt_bajo;
- }
-
- void intercambiar (float& valor1, float& valor2)
- {
- float temp = valor1;
- valor1 = valor2, valor2 = temp;
- }
-
- void visualizar_datos (float *dat, const int tam)
- {
- for (register int i = 0; i < tam; i++)
- cout << dat[i] << ' ';
- }
- ende
- end
-
- ; LECCION 3
- begin
- begine " CLASE ent "
- /*
- La función main() prueba la clase ent. La clase ent es similar al tipo int,
- diferenciándose en el tratamiento cuando se intenta sobrepasar los valores
- límites.
- */
-
- #include <iostream.h>
- #include <conio.h>
- #include <limits.h>
-
- class ent
- {
- int valor;
-
- public:
-
- void asig (int v = 0) { valor = v; }
- void incr (void) { if (valor < INT_MAX) valor++; }
- void decr (void) { if (valor > INT_MIN) valor--; }
- int val (void) { return valor; }
- };
-
- void main (void)
- {
- int i;
- ent e;
-
- cout << "EJEMPLO DE LA CLASE ent\n\n";
-
- cout << "i: " << (i = INT_MAX) << '\n';
- cout << "e: " << (e.asig (INT_MAX), e.val ()) << '\n';
- cout << "++i: " << ++i << '\n';
- cout << "++e: " << (e.incr (), e.val ()) << '\n';
- cout << "i: " << (i = INT_MIN) << '\n';
- cout << "e: " << (e.asig (INT_MIN), e.val ()) << '\n';
- cout << "--i: " << --i << '\n';
- cout << "--e: " << (e.decr (), e.val ()) << '\n';
-
- getch ();
- }
- ende
- begine " CLASE cola_char "
- /*
- Este ejemplo consiste en la creación de una clase cola_char y una función
- main() para probar dicha clase. En la cola de caracteres se pueden realizar
- dos operaciones: introducir y sacar caracteres, teniendo en cuenta siempre
- que el primer elemento introducido es el primer elemento a sacar.
- */
-
- #include <iostream.h>
- #include <conio.h>
-
- #define MAX 256
-
- class cola_char
- {
- char c[MAX];
- int posinic, posfinal;
-
- public:
-
- void inicializar_cola (void)
- {
- posfinal = 1; posinic = 0;
- }
-
- char guardar_en_cola (char car)
- {
- return (posfinal == MAX ? 0 : (c[posfinal++] = car));
- }
-
- char devolver_de_cola (void)
- {
- return (posinic + 1 == posfinal ? 0 : c[++posinic]);
- }
- };
-
- void main (void)
- {
- char s[MAX];
- cola_char cola;
- char ch;
-
- cout << "EJEMPLO DE LA CLASE cola_char\n\n";
-
- cola.inicializar_cola ();
- cout << "Introduce cadena a introducir en la cola de caracteres: ";
- cin >> s;
- for (char *ps = s; *ps && cola.guardar_en_cola (*ps); ps++)
- ;
- cout << "Cadena sacada de la cola: ";
- while ((ch = cola.devolver_de_cola ()) != 0)
- cout << ch;
-
- getch ();
- }
- ende
- end
-
- ; LECCION 4
- begin
- begine " CLASE conj_int "
- /*
- Este programa implementa la clase conj_int (conjunto de enteros) y
- desarrolla una función main() para testear dicha clase. La función
- main() crea e imprime un conjunto de números enteros aleatorios.
- */
-
- #include <iostream.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <time.h>
-
- class conj_int
- {
- int tamact, tammax;
- int *x;
-
- public:
-
- conj_int (int m, int n); // como mucho m enteros en el rango 1...n
- ~conj_int (void);
-
- int miembro (int elem); // ¿es "elem" un miembro?
- void insertar (int elem); // añade "elem" al conjunto
-
- // estas tres funciones son proporcionadas para que el usuario puede acceder
- // a los elementos del conjunto en algún orden
- void iterar (int& i) { i = 0; } // inicializa una iteración
- int ok (int& i) { return i < tamact; } // chequea si hay un miembro siguiente
- int siguiente (int& i) { return x[i++]; } // obtiene el siguiente miembro
- };
-
- inline void inicializar_generador_de_numeros_aleatorios (void)
- {
- srand (unsigned (time (NULL)));
- }
-
- inline int randint (int tope) // en el rango 1..tope
- {
- return 1 + rand() % tope;
- }
-
- void main (void)
- {
- void imprimir_en_orden (conj_int&);
-
- cout << "EJEMPLO DE LA CLASE conj_int\n\n";
-
- int contador = 0;
- int m, n;
-
- cout << "Introduce el número de miembros del conjunto: ";
- cin >> m;
-
- cout << "Introduce el valor máximo de los miembros del conjunto: ";
- cin >> n;
-
- conj_int conj (m, n);
-
- inicializar_generador_de_numeros_aleatorios ();
- while (contador < m)
- {
- int t = randint (n);
- if (conj.miembro (t) == 0) // evita elementos duplicados en el conjunto
- {
- conj.insertar (t);
- contador++;
- }
- }
-
- cout << "Elementos en el conjunto de enteros: ";
- imprimir_en_orden (conj);
-
- getch ();
- }
-
- void error (char *s)
- {
- cerr << "\n" << "conjunto: " << s << "\n";
- getch ();
- exit (1);
- }
-
- conj_int::conj_int (int m, int n) // como mucho m enteros en el rango 1..n
- {
- if (m < 1 || n < m)
- error ("tamaño de conj_int ilegal");
- tamact = 0;
- tammax = m;
- x = new int[tammax];
- }
-
- conj_int::~conj_int (void)
- {
- delete x;
- }
-
- void conj_int::insertar (int elem)
- {
- if (++tamact > tammax)
- error ("demasiados elementos");
- int i;
-
- for (i = tamact - 1, x[i] = elem; i > 0 && x[i-1] > x[i]; i--)
- {
- int elem = x[i]; // intercambia x[i] y x[i-1]
- x[i] = x[i-1];
- x[i-1] = elem;
- }
- }
-
- int conj_int::miembro (int elem) // búsqueda binaria
- {
- int ibaj = 0, ialt = tamact - 1;
-
- while (ibaj <= ialt)
- {
- int imed = (ibaj + ialt) / 2;
- if (elem < x[imed])
- ialt = imed - 1;
- else if (elem > x[imed])
- ibaj = imed + 1;
- else
- return 1; // encontrado
- }
- return 0; // no encontrado
- }
-
- void imprimir_en_orden (conj_int& conjunto)
- {
- int var;
- conjunto.iterar (var);
- while (conjunto.ok (var))
- cout << conjunto.siguiente (var) << " ";
- }
- ende
- begine " CLASE lista "
- /*
- Este programa implementa la clase lista, la cual maneja una lista lineal
- enlazada de caracteres. La función main() es un test para probar la clase
- lista.
- */
-
- #include <iostream.h>
-
- #ifndef NULL // en algunos sistemas puede que no esté definido en
- # define NULL 0 // iostream.h o stream.h
- #endif
-
- struct nodo_lista
- {
- char dato;
- nodo_lista *psiguiente;
- };
-
- class lista
- {
- nodo_lista *pcabeza; // cabeza de la lista
-
- public:
-
- lista (void) { pcabeza = NULL; }
- ~lista (void) { liberar (); }
-
- void aniadir (char c) // inserta al principio de la lista
- {
- nodo_lista *ptemp = new nodo_lista; // crea un nuevo elemento
- ptemp->psiguiente = pcabeza; // enlaza con lista
- ptemp->dato = c;
- pcabeza = ptemp; // actualiza la cabeza de la lista
- }
-
- void quitar (void) // quita primer elemento de la lista
- {
- nodo_lista *ptemp = pcabeza;
- pcabeza = pcabeza->psiguiente;
- delete ptemp;
- }
-
- nodo_lista *primero (void) { return pcabeza; }
- void imprimir_lista (void);
- void lista::liberar (void);
- };
-
- void lista::imprimir_lista (void)
- {
- for (nodo_lista *ptemp = pcabeza; ptemp != NULL; ptemp = ptemp->psiguiente)
- cout << ptemp->dato << " -> ";
- cout << "NULL\n";
- }
-
- void lista::liberar (void)
- {
- while (pcabeza != NULL)
- quitar ();
- }
-
- void main (void)
- {
- char s[256];
- lista list;
-
- cout << "EJEMPLO DE LA CLASE lista\n\n";
-
- cout << "Introduce cadena a introducir en la lista de caracteres: ";
- cin >> s;
- for (char *ps = s; *ps; ps++)
- list.aniadir (*ps);
- cout << "Contenido de la lista: ";
- list.imprimir_lista ();
-
- getch ();
- }
- ende
- begine " CLASE timer "
- /*
- Este ejemplo implementa la clase timer (contador de tiempo) junto con la
- función main() para probarla.
-
- La clase timer es más útil de lo que puede parecer a simple vista, ya que
- permite realizar programas que funcionan a la misma velocidad en cualquier
- tipo de ordenador. Esto es especialmente importante en los juegos de orde-
- nadores.
-
- Si tienes un ordenador que funciona en modo turbo y en modo normal, puedes
- cambiar entre modos turbo y normal mientras se ejecuta este programa para
- comprobar que las dos frases siguen escribiéndose a la misma velocidad.
-
- Como en todos los programas ejemplos del tutor de C++, es conveniente
- declarar la clase, las funciones inline y las declaraciones (no defini-
- ciones) de las variables globales y funciones no inline en un fichero de
- cabecera, y las definiciones de las funciones no inline y de las variables
- globales en fichero con extensión CPP. Por ejemplo, tendríamos entonces
- los ficheros timer.h y timer.cpp; en el fichero timer.cpp debemos incluir
- timer.h y entonces compilarlo para obtener el fichero objeto: timer.obj.
- Una vez que hemos hecho todo esto, para utilizar esta clase en un programa,
- debemos incluir, bien el fichero timer.cpp o bien el fichero timer.obj, en
- el fichero de proyecto; además, en el fichero que se encuentra nuestro
- programa incluimos el fichero de cabecera timer.h. Compilando el fichero
- de proyecto, tenemos el programa ejecutable final. Si nuestro programa no
- se va a desarrollar como proyecto, simplemente incluiremos el fichero
- timer.cpp en el fichero que forma nuestro programa. Este proceso, insisto,
- es válido para todos los programas ejemplos del tutor de C++.
- */
-
- #include <iostream.h> // cout
- #include <time.h> // clock (), CLK_TCK, clock_t
- #include <conio.h> // getch ()
-
- // La clase timer permite ejecutar retrasos y sincronizaciones, sin
- // necesidad de inicializaciones o variables adicionales.
-
- class timer
- {
- private:
- clock_t tinicial;
- public:
- timer (void);
- void esperar (int pulsos);
- void esperar (double segundos);
- void sincronizar (int pulsos);
- void sincronizar (double segundos);
- };
-
- // Cada vez que se crea un objeto (ya sea por declaración o utilizando new),
- // su constructor almacena en tinicial el instante de creación.
-
- inline timer::timer (void)
- {
- tinicial = clock ();
- }
-
- /*
- El argumento correcto para las dos funciones esperar debería ser unsigned.
- Para ello hay dos soluciones, bien llamar a cada función esperar con un
- nombre distinto, o bien llamar a las dos funciones iguales (sobrecarga de
- funciones) y hacer que los argumentos sean distintos. En este caso, y por
- cuestiones de claridad, es mejor optar por la segunda solución. Ejemplo:
- esperar (10); // espera 10 pulsos de reloj
- esperar (10.0); // espera 10 segundos
- El motivo de elegir int y double en vez de otra combinación (por ejemplo,
- unsigned y double, o int y long) es por motivo de errores de ambigüedad
- en las conversiones implícitas.
- Con las dos funciones de sincronizar ocurre lo mismo.
- */
-
- // espera el número indicado de pulsos
-
- void timer::esperar (int pulsos)
- {
- clock_t tfinal = clock () + pulsos;
- while (clock () < tfinal)
- ;
- }
-
- // espera el número indicado de segundos
-
- inline void timer::esperar (double segundos)
- {
- esperar (int (segundos * CLK_TCK) + 1);
- }
-
- // sincroniza el número indicado de pulsos
-
- void timer::sincronizar (int pulsos)
- {
- clock_t tfinal = tinicial + pulsos;
- while (clock () < tfinal)
- ;
- tinicial = clock ();
- }
-
- // sincroniza el número indicado de segundos
-
- inline void timer::sincronizar (double segundos)
- {
- sincronizar (int (segundos * CLK_TCK) + 1);
- }
-
- void main (void)
- {
- timer t;
- register const char *p;
- const char *frase1 = "Esta es la primera frase.";
- const char *frase2 = "Esta es la segunda frase.";
-
- clrscr ();
-
- cout << "\nEjemplo de la clase timer. En la primera frase, cada letra se "
- "escribirá un\ncuarto de segundo después de que se haya terminado "
- "de escribir la anterior.\nEn la segunda frase, cada letra se "
- "escribirá un cuarto de segundo después\n de que se haya empezado "
- "a escribir la anterior.\n\n";
-
- for (t.sincronizar (0.0), p = frase1; *p; p++)
- {
- cout << *p;
- t.esperar (int (CLK_TCK / 4));
- }
-
- for (cout << '\n', t.sincronizar (0.0), p = frase2; *p; p++)
- {
- cout << *p;
- t.sincronizar (int (CLK_TCK / 4));
- }
-
- cout << "\n\nPulsa cualquier tecla para salir de programa.";
- getch ();
- }
- ende
- begint
- begine " CLASE video "
- /*
- Este ejemplo implementa la clase video y una función main para probar dicha
- clase.
-
- La clase vídeo ofrece una implementación para poder acceder directamente a
- la memoria RAM de vídeo.
-
- El acceso directo a la memoria RAM de vídeo es mucho más rápido que el acceso
- vía interrupciones de la ROM BIOS. La desventaja que tiene con respecto al
- uso de dichas interrupciones es que es menos portable; no obstante, en la
- inmensa mayoría de los sistemas coincide la dirección de comienzo de la me-
- moria de vídeo: 0xB000:0x0000 para tarjetas monocromas (no monitores mono-
- cromos) y 0xB800:0x0000 para tarjetas color.
-
- Es importante hacer notar que la clase vídeo está implementada para que
- funcione sólamente con el modo de vídeo 80x25, es decir, el modo de vídeo
- que trabaja con 80 columnas y 15 filas. Para utilizar otros modos de vídeo
- sólo hace falta modificar las macros DIMX (dimensión del eje x) y DIMY (di-
- mensión del eje y). Sin embargo, sería más interesante que la propia clase
- averiguara cúal es el modo de pantalla actual; esto se deja como ejercicio.
- */
-
- #include <dos.h> // MK_FP ()
- #include <graphics.h> // detectgraph (), HERCMONO
- #include <conio.h> // getch ()
-
- #define DIMX 80
- #define DIMY 25
-
- // esta clase permite escribir (leer) carácteres en (de) la consola utilizando
- // directamente la memoria RAM de vídeo, es decir, el acceso a la memoria de
- // de vídeo no se hace vía interrupción de la ROM BIOS que sería más lento,
- // aunque también más portable
- class video
- {
- private :
-
- unsigned int (far *pantalla) [DIMX];
- unsigned char atributo;
-
- public :
-
- // constructor: inicializa las dos variables privadas
- // - pantalla apunta al principio de la memoria de vídeo
- // - atributo se pone por defecto en blanco sobre negro (0x07)
- video (void)
- {
- int gd, gm;
- detectgraph (&gd, &gm);
- pantalla = (unsigned int (far *) [DIMX])
- MK_FP (gd == HERCMONO ? 0xB000 : 0xB800, 0);
- atributo = 7; // blanco sobre negro
- }
-
- // escribe el carácter caract con el atributo atr en la posición (x,y)
- // de la pantalla sin comprobar que dicha posición está dentro de la
- // pantalla
- void _escr (int x, int y, int caract, unsigned char atr)
- {
- // (unsigned char) para escribir bien los códigos ascii > 128
- // pantalla[y-1][x-1] == (*(pantalla+y-1))[x-1] == *(*(pantalla+y-1)+x-1)
- *(*(pantalla+y-1)+x-1) = (atr << 8) + (unsigned char) caract;
- }
-
- // escribe el carácter caract con el atributo actual de pantalla en la
- // posición (x,y) de la pantalla sin comprobar que dicha posición está
- // dentro de la pantalla
- void _escr (int x, int y, int caract)
- {
- _escr (x, y, caract, atributo);
- }
-
- // escribe el carácter caract con el atributo atr de pantalla en la
- // posición (x,y) de la pantalla si esta posición es correcta
- void escr (int x, int y, int caract, unsigned atr)
- {
- if (x >= 1 && x <= DIMX && y >= 1 && y <= DIMY)
- _escr (x, y, caract, atr);
- }
-
- // escribe el carácter caract con el atributo actual de pantalla en la
- // posición (x,y) de la pantalla si esta posición es correcta
- void escr (int x, int y, int caract)
- {
- escr (x, y, caract, atributo);
- }
-
- // devuelve carácter que hay en la posicón (x,y) de la pantalla
- char leerc (int x, int y)
- {
- return pantalla[y-1][x-1];
- }
-
- // devuelve el atributo de pantalla de la posición (x,y) de ésta
- char leera (int x, int y)
- {
- return (pantalla[y-1][x-1] >> 4);
- }
-
- // devuelve el carácter que hay en la posición (x,y) de la pantalla
- int leer (int x, int y)
- {
- return pantalla[y-1][x-1];
- }
-
- // pone el atributo actual de pantalla
- void poner_atributo (unsigned char atr)
- {
- atributo = atr;
- }
- };
-
- void main (void)
- {
- video vid;
-
- for (register int x = 1; x <= DIMX; x++)
- for (register int y = 1; y <= DIMY; y++)
- vid._escr (x, y, x <= DIMX / 2 ? '▒' : '▓', y <= DIMY / 2 ? 0x07 : 0x70);
- for (x = 1; x <= DIMX; x++)
- vid._escr (x, DIMY, '░', x <= DIMX / 2 ? 0x07 : 0x70);
-
- vid.escr (DIMX + 1, DIMY + 1, '*'); // el carácter '*' no se escribirá
-
- getch ();
- }
- ende
- endt
- end
-
- ; LECCION 5
- begin
- begine " CLASE pot "
- /*
- Este ejemplo implementa la clase pot. La función main() prueba dicha clase.
- La clase pot nos permite elevar un número a la potencia de otro utilizando
- el operador ^ que es mucho más cómodo que utilizar la función pow().
-
- Notad que dependiendo de los operandos del operador ^, el compilador lo
- interpreta como operador XOR u operador de potencia.
- */
-
- #include <iostream.h> // cout, << sobrecargado
- #include <conio.h> // getch ()
- #include <math.h> // pow ()
-
- class pot
- {
- private:
- double num;
-
- public:
- pot (double d = 0.0) { num = d; }
- friend double operator^ (pot num1, pot num2) { return pow (num1, num2); }
- operator double () { return num; }
- };
-
- inline void imprimir_operacion (const char *operacion)
- {
- cout << "\n*** Ejecutando: " << operacion;
- }
-
- inline void imprimir_variables (pot x, pot y, double z)
- {
- cout << "\nx = " << double (x) << "\ny = " << double (y) << "\nz = " << z;
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE pot\n\n";
-
- cout << "\n*** Declarando: pot x = 5.5, y; double z = x;";
- pot x = 5.5, y; double z = x;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("y = z = x;");
- y = z = x;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("x = -2 + double (5) - pot (1);");
- x = -2 + double (5) - pot (1);
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("y = z ^ x;");
- y = z ^ x;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("z += x ^ (3 ^ 2);");
- z += x ^ (3 ^ 2); // 3 ^ 2 == 1 => XOR. x ^ 1 == x => POT
- imprimir_variables (x, y, z);
-
- getch ();
- }
- ende
- begine " CLASE vect "
- /*
- En este ejemplo se implementa la clase vect. La función main() prueba esta
- clase.
-
- La clase vect implementa un vector de enteros en el se chequea el rango
- cada vez que se accede al vector para asegurar que no accedamos a un
- elemento inexistente. Además, sobrecarga algunos operadores para realizar
- determinadas operaciones aritméticas y de asignación con los elementos de
- los vectores.
-
- Notad que las funciones de los operadores de asignación y la de indexado
- devuelven una referencia a vect mientras que las funciones de los operadores
- aritméticos devuelven un vect (esto es, un objeto temporal). Esto se suele
- hacer así en estos casos para permitir las siguientes sentencias:
- x[1] = 10;
- x = y = z;
- y para prohibir las siguientes:
- x + y = z;
- -x = y;
- */
-
- #include <iostream.h> // cout, cin
- #include <stdlib.h> // exit()
- #include <conio.h> // getch()
-
- // Un tipo seguro de array: chequea rangos
- class vect
- {
- int *p; // puntero base
- int tam; // número de elementos
-
- public:
-
- // constructores y destructor
- vect (void); // crea un array de 10 elementos
- vect (int n); // crea un array de n elementos
- vect (vect& v); // inicialización por vector
- vect (int a[], int n); // inicialización por array
- ~vect (void) { delete p; }
-
- // otras funciones miembros
- int is (void) { return (tam - 1); } // índice superior
- int& operator [] (int i);
- vect& operator = (vect& v);
- vect& operator += (vect& v);
- vect& operator -= (vect& v);
- vect operator - (void);
- vect operator + (void) { return (*this); }
- vect operator - (vect& v);
- vect operator + (vect& v);
-
- void imprimir (const char *mensaje);
- };
-
- void error (const char *msj)
- {
- cerr << "\nError en clase vect: " << msj << "\n";
- getch ();
- exit (1);
- }
-
- vect::vect (void)
- {
- p = new int[tam = 10];
- }
-
- vect::vect (int n)
- {
- if (n < 0)
- error ("Tamaño ilegal de vector.");
- p = new int[tam = n];
- }
-
- vect::vect (int a[], int n)
- {
- if (n < 0)
- error ("Tamaño ilegal de vector.");
- p = new int[tam = n];
- for (int i = 0; i < tam; ++i)
- p[i] = a[i];
- }
-
- vect::vect (vect& v)
- {
- p = new int[tam = v.tam];
- for (int i = 0; i < tam; ++i)
- p[i] = v.p[i];
- }
-
- int& vect::operator [] (int i)
- {
- if (i < 0 || i > is ())
- error ("Indice de vector ilegal.");
- return p[i];
- }
-
- vect& vect::operator = (vect& v)
- {
- int t = tam < v.tam ? tam : v.tam;
- if (v.tam != tam)
- error ("Intento de copiar arrays de tamaños diferentes.");
- for (int i = 0; i < t; ++i)
- p[i] = v.p[i];
- return *this;
- }
-
- vect& vect::operator += (vect& v)
- {
- return (*this = *this + v);
- }
-
- vect& vect::operator -= (vect& v)
- {
- return (*this = *this - v);
- }
-
- vect vect::operator - (void)
- {
- vect neg (*this);
- for (int i = 0; i < tam; ++i)
- neg.p[i] = -neg.p[i];
- return neg;
- }
-
- vect vect::operator - (vect& v)
- {
- int t = tam < v.tam ? tam : v.tam;
- vect dif (t);
- if (v.tam != tam)
- error ("Intento de sumar arrays de tamaños diferentes.");
- for (int i = 0; i < t; ++i)
- dif.p[i] = p[i] - v.p[i];
- return dif;
- }
-
- vect vect::operator + (vect& v)
- {
- return (*this - -v);
- }
-
- void vect::imprimir (const char *mensaje)
- {
- cout << '\n' << mensaje << ": [";
- for (register int i = 0; i < tam; i++)
- cout << ' ' << p[i];
- cout << " ]";
- }
-
- void imprimir_operacion (const char *operacion,
- vect& vectx, vect& vecty, vect& vectz)
- {
- cout << "\nEjecutando: " << operacion;
- vectx.imprimir ("Vector x");
- vecty.imprimir ("Vector y");
- vectz.imprimir ("Vector z");
- cout << '\n';
- getch ();
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE vect\n\n";
-
- int n;
- register int i;
-
- do
- {
- cout << "Introduce número de elementos de los vectores x e y: ";
- cin >> n;
- } while (n <= 0);
-
- int *vx = new int[n], *vy = new int[n];
-
- cout << "Introduce los " << n << " elementos del vector x: ";
- for (i = 0; i < n; i++)
- cin >> vx[i];
-
- cout << "Introduce los " << n << " elementos del vector y: ";
- for (i = 0; i < n; i++)
- cin >> vy[i];
-
- vect x (vx, n), y (vy, n), z (n);
- imprimir_operacion ("inicialización de los vectores x, y", x, y, z);
-
- z = x + y;
- imprimir_operacion ("z = x + y;", x, y, z);
-
- x += y = -z;
- imprimir_operacion ("x += y = -z;", x, y, z);
-
- y = z - (x = y);
- imprimir_operacion ("y = z - (x = y);", x, y, z);
-
- y += z -= x;
- imprimir_operacion ("y += z -= x;", x, y, z);
-
- z = -(- (x - (+y) - z));
- imprimir_operacion ("z = -(- (x - (+y) - z));", x, y, z);
-
- y = -(-z - -x);
- imprimir_operacion ("y = -(-z - -x);", x, y, z);
-
- cout << "\nEjecutando: x[" << n << "];";
- x[n];
-
- delete vx;
- delete vy;
- }
- ende
- begine " CLASE intpeq "
- /*
- Este ejemplo implementa la clase intpeq junto con la función main() para
- probar esta clase.
-
- La clase intpeq es igual que la clase int con la excepción de que los
- objetos del tipo intpeq sólo pueden tomar valores entre 0 y 63. El rango
- sólo se chequea cuando un intpeq es inicializado con un int y cuando se
- asigna un int a un intpeq.
- */
-
- #include <iostream.h>
- #include <conio.h>
-
- inline void err (const char *mensaje_de_error)
- {
- cout << '\n' << mensaje_de_error;
- }
-
- class intpeq
- {
- char val;
- int asign (int i) { return val = (i&~63) ? (err ("error de rango"), 0) : i; }
-
- public:
-
- intpeq (int i) { asign (i); }
- intpeq (intpeq& ip) { val = ip.val; } // no chequeo de rango (innecesario)
- int operator= (int i) { return asign (i); }
- int operator= (intpeq& ip) { return val = ip.val; } // no chequeo de rango
- operator int () { return val; }
- };
-
- inline void impr_operacion (const char *operacion)
- {
- cout << "\n*** Ejecutando: " << operacion;
- }
-
- inline void impr_variables (intpeq x, intpeq y, int z)
- {
- cout << "\nx = " << int (x) << "\ny = " << int (y) << "\nz = " << z;
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE intpeq";
-
- cout << "\n*** Declarando: intpeq x = 3, y = 62; int z = 64;";
- intpeq x = 3, y = 62; int z = 64;
- impr_variables (x, y, z);
-
- impr_operacion ("y = x + y, x = z;");
- y = x + y, x = z;
- impr_variables (x, y, z);
-
- impr_operacion ("x = y * 2 + z - 4;");
- x = y * 2 + z - 4;
- impr_variables (x, y, z);
-
- impr_operacion ("y = x * x;");
- y = x * x;
- impr_variables (x, y, z);
-
- impr_operacion ("z = x + 10, x = -1;");
- z = x + 10, x = -1;
- impr_variables (x, y, z);
-
- getch ();
- }
- ende
- begine " CLASE arbol_binario "
- /*
- Este programa implementa la clase arbol_binario junto con una función main()
- para probarla.
-
- La clase arbol_binario permite al usuario realizar varias operaciones con
- árboles binarios: insertar, buscar, quitar, listar, ...
- */
-
- #include <iostream.h> // cout, cin, cerr
- #include <stdlib.h> // exit (), NULL
- #include <conio.h> // getch ()
-
- enum boolean { false, true };
-
- struct nodo_arbol_binario
- {
- friend class arbol_binario;
-
- private:
-
- char dato;
- nodo_arbol_binario *pizquierdo, *pderecho;
-
- };
-
- class arbol_binario
- {
- nodo_arbol_binario *parbol; // puntero a la cabeza del árbol
-
- public:
-
- arbol_binario (void) { parbol = NULL; }
- ~arbol_binario (void) { liberar_arbol (); }
-
- void liberar_arbol (void) { liberar (parbol); parbol = NULL; }
- void insertar (char dat);
- boolean quitar_de_arbol (char dat);
- boolean buscar_en_arbol (char dat) { return boolean (buscar (dat) != NULL); }
-
- void imprimir_arbol_en_preorden (void) { imprimir_en_preorden (parbol); }
- void imprimir_arbol_en_postorden (void) { imprimir_en_postorden (parbol); }
- void imprimir_arbol_en_inorden (void) { imprimir_en_inorden (parbol); }
-
- private:
-
- nodo_arbol_binario *buscar (char dat);
- void suprimir_nodo_de_arbol (nodo_arbol_binario * &p);
-
- void imprimir_en_preorden (nodo_arbol_binario *parb);
- void imprimir_en_postorden (nodo_arbol_binario *parb);
- void imprimir_en_inorden (nodo_arbol_binario *parb);
-
- void liberar (nodo_arbol_binario * &parb);
-
- void crear_nodo_arbol (nodo_arbol_binario * &pa)
- {
- if ((pa = new nodo_arbol_binario) == NULL)
- {
- cerr << "\nERROR: Memoria insuficiente.";
- getch ();
- exit (1);
- }
- }
-
- void liberar_nodo_arbol (nodo_arbol_binario * &pa) { delete pa; }
- };
-
- /*
- Cuando se destruye el objeto árbol es conveniente liberar la memoria
- asignada dinámicamente. Para ello, lo único que se hace es recorrer
- todo el árbol liberando cada nodo con delete.
- */
-
- void arbol_binario::liberar (nodo_arbol_binario * &parb)
- {
- if (parb != NULL)
- {
- liberar (parb->pizquierdo);
- liberar (parb->pderecho);
- liberar_nodo_arbol (parb);
- }
- }
-
- /*
- Para ver cómo se inserta en lo árboles, veamos cómo se insertarían
- los siguientes números en un árbol donde información es un número
- entero:
-
- 3 10 2 -1 0 3 8 20
-
- Paso 0:
- parbol
- │
- v
- NULL
- Paso 1:
- parbol
- │
- v
- 3
- Paso 2:
- parbol
- │
- v
- 3
- \
- 10
- Paso 3:
- parbol
- │
- v
- 3
- / \
- 2 10
- Paso 4:
- parbol
- │
- v
- 3
- / \
- 2 10
- /
- -1
- Paso 5:
- parbol
- │
- v
- 3
- / \
- 2 10
- /
- -1
- \
- 0
- Paso 6:
- parbol
- │
- v
- 3
- / \
- 2 10
- / /
- -1 3
- \
- 0
- Paso 7:
- parbol
- │
- v
- 3
- / \
- 2 10
- / /
- -1 3
- \ \
- 0 8
- Paso 8:
- parbol
- │
- v
- 3
- / \
- 2 10
- / / \
- -1 3 20
- \ \
- 0 8
-
- */
-
- void arbol_binario::insertar (char dat)
- {
- nodo_arbol_binario *p, *pant; /* punteros utilizados para la búsqueda */
- nodo_arbol_binario *pa; /* puntero que apunta a nuevo nodo creado y que hay que insertar */
-
- crear_nodo_arbol (pa);
- pa->dato = dat;
- pa->pizquierdo = pa->pderecho = NULL;
-
- p = parbol;
- pant = NULL;
- while (p != NULL) /* busca lugar de inserción */
- {
- pant = p;
- if (p->dato > dat)
- p = p->pizquierdo;
- else
- p = p->pderecho;
- }
-
- if (pant == NULL) /* inserta en lugar correspondiente */
- parbol = pa;
- else if (pant->dato > dat)
- pant->pizquierdo = pa;
- else
- pant->pderecho = pa;
- }
-
- /*
- Quita el primer nodo encontrado que contenga el valor dat en el
- campo información del nodo.
- Devuelve true si se borró el elemento o false en caso contrario.
- */
-
- boolean arbol_binario::quitar_de_arbol (char dat)
- {
- nodo_arbol_binario *p = parbol, *pant = NULL;
- boolean encontrado = false;
-
- while (p != NULL && ! encontrado) /* busca nodo a borrar */
- if (p->dato == dat)
- encontrado = true;
- else
- {
- pant = p;
- if (p->dato > dat)
- p = p->pizquierdo;
- else
- p = p->pderecho;
- }
-
- if (encontrado) /* llama a la función suprimir con puntero apuntado a nodo a quitar */
- if (p == parbol)
- suprimir_nodo_de_arbol (parbol);
- else if (pant->pizquierdo == p)
- suprimir_nodo_de_arbol (pant->pizquierdo);
- else
- suprimir_nodo_de_arbol (pant->pderecho);
-
- return (encontrado);
- }
-
- /*
- Suprime nodo de árbol apuntado por p.
- Esta función es llamada por la función quitar_de_arbol.
-
- Hay tres situaciones diferentes a la hora de suprimir un nodo, a saber:
-
- Sea el árbol compuesto de números reales:
-
- 5
- / \
- 3 8
- / \ / \
- 2 4 6 9
- / / \
- 1 5.5 7
- /
- 6.5
-
- Situación 1: suprimir nodo sin hijo derecho; por ejemplo, el nodo 7, en
- este caso el puntero p es el puntero derecho del nodo 6; la acción a
- realizar es: p = pizq (p).
-
- Situación 2: suprimir nodo sin hijo izquierdo; por ejemplo, el nodo 1, en
- este caso el puntero p es el puntero izquierdo del nodo 2; la acción a
- realizar es: p = pder (p).
-
- Situación 3: suprimir nodo intermedio, es decir, nodo con hijos izquierdo
- y derecho; por ejemplo, el nodo 8, en este caso el puntero p es el
- puntero derecho del nodo 5; la acción a realizar es sustituir el contenido
- del nodo a suprimir (nodo 8) por el mayor contenido entre los nodos del
- subárbol izquierdo, que se calcula como el nodo más a la derecha a partir
- del nodo izquierdo del nodo a suprimir, en este caso el nodo izquierdo es
- 6 y recorriendo los punteros a la derecha hasta llegar al final, nos
- paramos en el nodo 7, copiamos el contenido del nodo 7 en el nodo 8 y
- ahora tenemos que suprimir un nodo (el 7 en este caso) que ya pertenece
- a uno de los dos casos anteriores.
- */
-
- void arbol_binario::suprimir_nodo_de_arbol (nodo_arbol_binario * &p)
- {
- nodo_arbol_binario *ptemp = p;
-
- if (p->pderecho == NULL) /* situación 1 */
- p = p->pizquierdo;
- else if (p->pizquierdo == NULL) /* situación 2 */
- p = p->pderecho;
- else /* situación 3 */
- {
- nodo_arbol_binario *pant = p;
- ptemp = p->pizquierdo;
- while (ptemp->pderecho != NULL) /* recorremos punteros a derecha a partir ... */
- { /* ... puntero a izquierda del nodo apuntado por el puntero a suprimir */
- pant = ptemp;
- ptemp = ptemp->pderecho;
- }
- p->dato = ptemp->dato;
- if (pant == p)
- pant->pizquierdo = ptemp->pizquierdo;
- else
- pant->pderecho = ptemp->pizquierdo;
- }
-
- liberar_nodo_arbol (ptemp);
- }
-
- /*
- Devuelve un puntero al nodo del árbol que contiene dat. Si ningún nodo
- del árbol contiene el dato dat, devuelve NULL.
- */
-
- nodo_arbol_binario *arbol_binario::buscar (char dat)
- {
- nodo_arbol_binario *p = parbol;
- boolean encontrado = false;
-
- while (p != NULL && ! encontrado)
- if (p->dato == dat)
- encontrado = true;
- else if (p->dato > dat)
- p = p->pizquierdo;
- else
- p = p->pderecho;
-
- return (p); /* p valdrá NULL si dat no se ha encontrado */
- }
-
- // Imprime todos los elementos del árbol parb haciendo un recorrido en preorden.
-
- void arbol_binario::imprimir_en_preorden (nodo_arbol_binario *parb)
- {
- if (parb != NULL)
- {
- cout << parb->dato;
- imprimir_en_preorden (parb->pizquierdo); /* imprime subárbol izquierdo */
- imprimir_en_preorden (parb->pderecho); /* imprime subárbol derecho */
- }
- }
-
- // Imprime todos los elementos del árbol parb haciendo un recorrido en postorden.
-
- void arbol_binario::imprimir_en_postorden (nodo_arbol_binario *parb)
- {
- if (parb != NULL)
- {
- imprimir_en_postorden (parb->pizquierdo); /* imprime subárbol izquierdo */
- imprimir_en_postorden (parb->pderecho); /* imprime subárbol derecho */
- cout << parb->dato;
- }
- }
-
- // Imprime todos los elementos del árbol parb haciendo un recorrido en inorden.
- // Si el árbol está ordenado, este recorrido imprime los elmentos ordenados.
-
- void arbol_binario::imprimir_en_inorden (nodo_arbol_binario *parb)
- {
- if (parb != NULL)
- {
- imprimir_en_inorden (parb->pizquierdo); /* imprime subárbol izquierdo */
- cout << parb->dato;
- imprimir_en_inorden (parb->pderecho); /* imprime subárbol derecho */
- }
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE arbol_binario\n\n";
-
- char s[256];
- arbol_binario arbol;
-
- cout << "Introduce cadena a introducir en el árbol: ";
- cin >> s;
- for (char *ps = s; *ps; ps++)
- arbol.insertar (*ps);
-
- cout << "\nContenido del árbol en preorden: ";
- arbol.imprimir_arbol_en_preorden ();
- cout << "\nContenido del árbol en postorden: ";
- arbol.imprimir_arbol_en_postorden ();
- cout << "\nContenido del árbol en inorden: ";
- arbol.imprimir_arbol_en_inorden ();
-
- cout << "\n\nBuscando dato '" << *s << "':"
- << (arbol.buscar_en_arbol (*s) ? " " : " no ") << "encontrado.";
- cout << "\nQuitando dato '" << *s << "'.";
- while (arbol.quitar_de_arbol (*s))
- ;
- cout << "\nBuscando dato '" << *s << "':"
- << (arbol.buscar_en_arbol (*s) ? " " : " no ") << "encontrado.";
-
- getch ();
- }
- ende
- begine " CLASE asoc "
- /*
- Este programa cuenta las ocurrencias de cada palabra leída de la entrada
- estándar. La entrada estándar es por defecto el teclado pero se puede
- redirigir el programa para que lea de un fichero.
-
- Este programa define la clase asoc (vector asociativo) cuyo interface
- con el exterior está compuesta por tres funciones: el constructor, el
- operador sobrecargado [] y una función de impresión.
-
- La estructura par sólo es utilizada por la clase asoc, por este motivo
- sus miembros son privados y sólo tiene acceso a ellos los miembros de
- la clase asoc. Observad que aunque la estructura par está declarada en
- el interior de la declaración de la clase asoc, en realidad, es como si
- estuviera declarada fuera; se ha declarado dentro para indicar al lector
- que dicha estructura solo es utilizada por la clase asoc.
- */
-
- #include <iostream.h> // cout, cin
- #include <conio.h> // getch ()
- #include <string.h> // strcmp (), strlen (), strcpy ()
-
- class asoc // vector asociativo
- {
- struct par // cada elemento del vector asociativo
- {
- friend class asoc; // sólo puede acceder la clase asoc a esta estructura
-
- private:
-
- char *nombre;
- int valor;
- };
-
- par *vect;
- int max; // tamaño del vector
- int libre; // índice del primer elemento del vector no usado
-
- public:
-
- asoc (int);
- int& operator[] (char *);
- void imprimir_todo (void);
- };
-
- asoc::asoc (int tam)
- {
- max = tam < 16 ? tam : 16;
- libre = 0;
- vect = new par[max];
- }
-
- /*
- Mantiene un conjunto de "par"es:
- busca cadena p en vector asociativo
- devuelve una referencia a la parte entera de su "par"
- crea un nuevo "par" si la cadena p no se encuentra
- */
-
- int& asoc::operator[] (char *p)
- {
- register par *pp;
-
- for (pp = &vect[libre-1]; vect <= pp; pp--)
- if (strcmp (p, pp->nombre) == 0)
- return pp->valor;
-
- if (libre == max) // desbordamiento: es necesario crecer el vector
- {
- par *nvect = new par[max*2];
- for (int i = 0; i < max; i++)
- nvect[i] = vect[i];
- delete vect;
- vect = nvect;
- max *= 2;
- }
-
- pp = &vect[libre++];
- pp->nombre = new char[strlen (p) + 1];
- strcpy (pp->nombre, p);
- pp->valor = 0; // valor inicial: 0
- return pp->valor;
- }
-
- void asoc::imprimir_todo (void)
- {
- for (int i = 0; i < libre; i++)
- cout << vect[i].nombre << ": " << vect[i].valor << "\n";
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE asoc\n\n";
-
- const MAX = 256; // palabra más larga
- char buf[MAX];
- asoc vect (512);
-
- while (cin >> buf)
- vect[buf]++;
- vect.imprimir_todo ();
-
- getch ();
- }
- ende
- begine " CLASE iterador_asociat "
- /*
- Este programa cuenta las ocurrencias de cada palabra leída de la entrada
- estándar. La entrada estándar es por defecto el teclado pero se puede
- redirigir el programa para que lea de un fichero.
-
- Este ejemplo hace exactamente lo mismo que el ejemplo anterior pero
- utilizando una forma más conveniente de hacerlo que el ejemplo precedente.
-
- Define la clase interador_asociat para que realice el trabajo de presentar
- los elementos del vector asociativo (clase asociat) en el mismo orden en
- el que se encuentran en dicho vector.
-
- Lo más interesante de este ejemplo es la sobrecarga del operador () que
- realiza las llamadas a las funciones. Una llamada a función, esto es, la
- notación expresion(lista_expresiones), puede ser interpretada como una
- operación binaria, y el operador de llamada () puede ser sobrecargado de
- la misma forma que los demás operadores. Una lista de argumentos para una
- función operator() es evaluada y chequeada acorde a las reglas usuales de
- paso de argumentos.
- */
-
- #include <iostream.h> // cout, cin
- #include <conio.h> // getch ()
- #include <string.h> // strcmp (), strlen (), strcpy ()
-
- struct par_asociat // cada elemento del vector asociativo
- {
- char *nombre;
- int valor;
- };
-
- class asociat // vector asociativo
- {
- friend class iterador_asociat;
-
- par_asociat *vect;
- int max; // tamaño del vector
- int libre; // índice del primer elemento del vector no usado
-
- public:
-
- asociat (int);
- int& operator[] (char *);
- };
-
- class iterador_asociat
- {
- asociat *ac; // array asociativo actual
- int i;
-
- public:
-
- iterador_asociat (asociat& a) { ac = &a; i = 0; }
- par_asociat *operator() (void) { return i < ac->libre ? &ac->vect[i++] : 0; }
- };
-
- asociat::asociat (int tam)
- {
- max = tam < 16 ? tam : 16;
- libre = 0;
- vect = new par_asociat[max];
- }
-
- /*
- Mantiene un conjunto de pares del vector asociativo ordenados:
- busca cadena p en vector asociativo
- devuelve una referencia a la parte entera de su par
- crea un nuevo par si la cadena p no se encuentra
- */
-
- int& asociat::operator[] (char *p)
- {
- register par_asociat *pp;
-
- for (pp = &vect[libre-1]; vect <= pp; pp--)
- if (strcmp (p, pp->nombre) == 0)
- return pp->valor;
-
- if (libre == max) // desbordamiento: es necesario crecer el vector
- {
- par_asociat *nvect = new par_asociat[max*2];
- for (int i = 0; i < max; i++)
- nvect[i] = vect[i];
- delete vect;
- vect = nvect;
- max *= 2;
- }
-
- pp = &vect[libre++];
- pp->nombre = new char[strlen (p) + 1];
- strcpy (pp->nombre, p);
- pp->valor = 0; // valor inicial: 0
- return pp->valor;
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE iterador_asoc\n\n";
-
- const MAX = 256; // palabra más larga
- char buf[MAX];
- asociat vect (512);
-
- while (cin >> buf)
- vect[buf]++;
-
- iterador_asociat siguiente (vect);
- par_asociat *p;
-
- while ((p = siguiente ()) != 0)
- cout << p->nombre << ": " << p->valor << "\n";
-
- getch ();
- }
- ende
- begine " CLASE fecha "
- /*
- Este programa desarrolla la clase fecha y la función main() para probarla.
- La clase fecha es infinitamente mejorable pues tiene muchas deficiencias,
- no obstante, aquí se ha dado la idea base para desarrollar una clase fecha
- mucho más perfeccionada.
- */
-
- #include <iostream.h> // cout
- #include <conio.h> // getch ()
- #include <dos.h> // int86 ()
- #include <stdlib.h> // atoi ()
-
- class fecha
- {
- private:
-
- int dia, mes, anio;
- long num_dias; // número de días desde 1900
- void convertir (void);
-
- public:
-
- fecha (void);
- fecha (int d, int m, int a);
- fecha (char *str);
-
- operator long () { return num_dias; }
- fecha operator+ (int num)
- { return fecha (dia + num, mes, anio); }
- fecha& operator+= (int num)
- { return *this = *this + num; }
- void ver (char *str) { cout << str << dia << '/' << mes << '/' << anio; }
- };
-
- // Calcula el número de días a partir del 1/1/1900
- void fecha::convertir (void)
- {
- int dias_meses;
-
- num_dias = 386 * (anio - 1900);
- switch (mes)
- {
- case 1 : dias_meses = 0; break;
- case 2 : dias_meses = 31; break;
- case 3 : dias_meses = 59; break;
- case 4 : dias_meses = 90; break;
- case 5 : dias_meses = 120; break;
- case 6 : dias_meses = 151; break;
- case 7 : dias_meses = 181; break;
- case 8 : dias_meses = 212; break;
- case 9 : dias_meses = 243; break;
- case 10 : dias_meses = 273; break;
- case 11 : dias_meses = 304; break;
- case 12 : dias_meses = 334; break;
- }
- num_dias += dias_meses + dia;
- }
-
- // Asume fecha activa del sistema
- fecha::fecha (void)
- {
- union REGS r;
-
- r.h.ah = 0x2A; // obtener fecha del sistema (función 2Ah, int 21h)
- int86 (0x21, &r, &r);
- dia = r.h.dl;
- mes = r.h.dh;
- anio = r.x.cx;
- convertir ();
- }
-
- fecha::fecha (int d, int m, int a)
- {
- dia = d;
- mes = m;
- anio = a;
- convertir ();
- }
-
- // str ha de tener la forma: dd/mm/aaaa
- fecha::fecha (char *str)
- {
- dia = atoi (str);
- while (*str++ != '/')
- ;
- mes = atoi (str);
- while (*str++ != '/')
- ;
- anio = atoi (str);
- convertir ();
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE fecha";
-
- cout << "\n\n*** Declarando: fecha f1, f2 (1, 4, 1993), f3 (\"5/4/1993\");";
- fecha f1, f2 (1, 4, 1993), f3 ("5/4/1993");
-
- f1.ver ("\nf1: ");
- f2.ver ("\nf2: ");
- f3.ver ("\nf3: ");
-
- cout << "\n\n*** Ejecutando f3 - f2 para calcular diferencia de días.";
- cout << "\nNúmero de días entre ";
- f3.ver ("");
- cout << " y ";
- f2.ver ("");
- cout << ": " << f3 - f2;
-
- cout << "\n\n*** Ejecutando f2 += 3 para sumarle 3 días a la fecha f2.";
- f2 += 3;
- f2.ver ("\nf2: ");
-
- getch ();
- }
- ende
- end
-
- ; LECCION 6
- begin
- begine " CLASE vector_ind "
- /*
- En este ejemplo se implementa la clase vector_ind. La función main()
- prueba esta clase.
-
- La clase vector implementa un vector de enteros en el se chequea el rango
- cada vez que se accede al vector para asegurar que no accedamos a un
- elemento inexistente. Además, sobrecarga algunos operadores para realizar
- determinadas operaciones aritméticas y de asignación con los elementos de
- los vectores.
-
- La clase vector se implementó previamente, con el nombre de vect, en uno
- de los ejemplos de la lección anterior. En este caso, la clase vect la
- hemos hecho clase base de la clase vector_ind, con la cual podemos traba-
- jar con arrays seguros (se chequea rango) en los cuales especificamos
- índice mínimo y máximo del array.
- */
-
- #include <iostream.h> // cout, cin
- #include <stdlib.h> // exit()
- #include <conio.h> // getch()
-
- // Un tipo seguro de array: chequea rangos
- class vector
- {
- int *p; // puntero base
- int tam; // número de elementos
-
- public:
-
- // constructores y destructor
- vector (void); // crea un array de 10 elementos
- vector (int n); // crea un array de n elementos
- vector (vector& v); // inicialización por vector
- vector (int a[], int n); // inicialización por array
- ~vector (void) { delete p; }
-
- // otras funciones miembros
- int is (void) { return (tam - 1); } // índice superior
- int& operator [] (int i);
-
- void imprimir (const char *mensaje);
- void error (const char *mensaje);
- };
-
- // Un array con índices inferior y superior, esto es, con índice mínimo y
- // con índice máximo
- class vector_ind : public vector
- {
- int ind_inf, ind_sup; // índices inferior y superior del vector
-
- public:
-
- vector_ind (void);
- vector_ind (int ii, int is);
-
- int& operator[] (int i);
-
- int ii (void) { return (ind_inf); } // devuelve índice inferior
- int is (void) { return (ind_sup); } // devuelve índice superior
-
- void error (const char *mensaje);
- };
-
- vector::vector (void)
- {
- p = new int[tam = 10];
- }
-
- vector::vector (int n)
- {
- if (n < 0)
- error ("Tamaño ilegal de vector.");
- p = new int[tam = n];
- }
-
- vector::vector (int a[], int n)
- {
- if (n < 0)
- error ("Tamaño ilegal de vector.");
- p = new int[tam = n];
- for (int i = 0; i < tam; ++i)
- p[i] = a[i];
- }
-
- vector::vector (vector& v)
- {
- p = new int[tam = v.tam];
- for (int i = 0; i < tam; ++i)
- p[i] = v.p[i];
- }
-
- int& vector::operator [] (int i)
- {
- if (i < 0 || i > is ())
- error ("Indice fuera de rango.");
- return p[i];
- }
-
- void vector::imprimir (const char *mensaje)
- {
- cout << '\n' << mensaje << ": [";
- for (register int i = 0; i < tam; i++)
- cout << ' ' << p[i];
- cout << " ]";
- }
-
- void vector::error (const char *msj)
- {
- cerr << "\nError en clase vector: " << msj << "\n";
- getch ();
- exit (1);
- }
-
- vector_ind::vector_ind (void) : vector (10)
- {
- ind_inf = 0;
- ind_sup = 9;
- }
-
- vector_ind::vector_ind (int ii, int is): vector (is - ii + 1)
- {
- ind_inf = ii;
- ind_sup = is;
- }
-
- int& vector_ind::operator[] (int i)
- {
- if (i < ind_inf || i > ind_sup)
- error ("Indice fuera de rango.");
- return (vector::operator[] (i - ind_inf));
- }
-
- void vector_ind::error (const char *msj)
- {
- cerr << "\nError en clase vector_ind: " << msj << "\n";
- getch ();
- exit (1);
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE vector_ind\n";
-
- vector_ind x (-2, 7), y (4, 8), z;
- register int i;
-
- for (i = -2; i <= 7; i++)
- x[i] = i;
- for (i = 4; i <= 8; i++)
- y[i] = i;
- for (i = 0; i <= 9; i++)
- z[i] = i;
-
- x.imprimir ("\nVector x");
- y.imprimir ("\nVector y");
- z.imprimir ("\nVector z");
-
- cout << "\n";
- cout << "\nIntentando acceder a x[8] " << x[8];
-
- getch ();
- }
- ende
- end
-
- ; LECCION 7
- begin
- begine " CLASES PARA CONTADORES "
- /*
- Este programa muestra diversas clases cuyos objetos son utilizados como
- contadores.
-
- Primero se ha diseñado la clase contador, una vez hecho esto, es fácil
- añadirle mejoras creando clases derivadas de ésta sin tener que modificar
- para nada la clase base.
-
- Las clase base contador ha de ser virtual para las clases derivadas
- contador_con_valor_maximo y contador_con_valor_minimo para que no haya
- problemas al hacer estas dos clases derivadas de la clase contador,
- clase base de la clase contador_con_rango.
-
- La función main() se limita a probar las clases diseñadas para comprobar
- la manera en que funcionan dichas clases.
- */
-
- #include <iostream.h> // cout
- #include <limits.h> // INT_MAX, INT_MIN
- #include <conio.h> // getch ()
-
- class contador
- {
- private:
-
- int valor;
-
- public:
-
- contador (int valor_inicial = 0)
- {
- valor = valor_inicial;
- }
-
- void inc (void)
- {
- if (valor < INT_MAX)
- valor++;
- }
-
- void dec (void)
- {
- if (valor > INT_MIN)
- valor--;
- }
-
- void asig (int val)
- {
- valor = val;
- }
-
- int val (void)
- {
- return valor;
- }
- };
-
- class contador_con_valor_maximo : virtual public contador
- {
- private:
-
- int valor_maximo;
-
- public:
-
- contador_con_valor_maximo (int valmax) : contador ()
- {
- valor_maximo = valmax;
- }
-
- void inc (void)
- {
- if (val () < valor_maximo)
- contador::inc ();
- }
- };
-
- class contador_con_valor_minimo : virtual public contador
- {
- private:
-
- int valor_minimo;
-
- public:
-
- contador_con_valor_minimo (int valmin) : contador ()
- {
- asig (valor_minimo = valmin);
- }
-
- void dec (void)
- {
- if (val () > valor_minimo)
- contador::dec ();
- }
- };
-
- class contador_con_rango : public contador_con_valor_maximo,
- public contador_con_valor_minimo
- {
- public:
-
- contador_con_rango (int valmin, int valmax) :
- contador_con_valor_minimo (valmin),
- contador_con_valor_maximo (valmax)
- { }
- };
-
- void main (void)
- {
- contador c;
- contador_con_valor_maximo cmaximo (10);
- contador_con_valor_minimo cminimo (5);
- contador_con_rango crango (-5, 5);
-
- register int i;
-
- cout << "EJEMPLO SOBRE LAS CLASES DE CONTADORES.";
-
- c.asig (INT_MAX - 3);
- cout << "\n\nProbando objeto de tipo contador: " << c.val ();
- for (i = 1; i <= 5 ; i++)
- {
- c.inc ();
- cout << ' ' << c.val ();
- }
-
- cmaximo.dec ();
- cout << "\n\nProbando objeto de tipo contador_con_valor_maximo: " << cmaximo.val ();
- for (i = 0; i <= 7; i++)
- {
- cmaximo.inc ();
- cout << ' ' << cmaximo.val ();
- }
-
- cminimo.asig (10);
- cout << "\n\nProbando objeto de tipo contador_con_valor_minimo: " << cminimo.val ();
- for (i = cminimo.val (); i >= 3; i--)
- {
- cminimo.dec ();
- cout << ' ' << cminimo.val ();
- }
-
- cout << "\n\nProbando objeto de tipo contador_con_rango:";
- for (i = -5; i <= 5; i++, crango.inc ())
- {
- cout << ' ' << crango.val ();
- }
-
- getch ();
- }
- ende
- end
-
- ; LECCION 8
- begin
- begine " CLASE fraccion "
- /*
- Este ejemplo implementa la clase fraccion y una función main() para probar
- esta clase.
- La clase fraccion nos permite trabajar con fracciones. Las fracciones son
- números reales en la forma: numerador/denominador.
- Observad la sobrecarga de los operadores << y >>. Sobrecargar estos opera-
- dores es más cómodo que implementar métodos para imprimir como podría ser:
- void fraccion::imprimir (void).
- */
-
- #include <iostream.h> // cout, << sobrecargado
- #include <stdlib.h> // abs ()
- #include <conio.h> // getch ()
-
- class fraccion
- {
- private:
-
- long numerador, denominador;
-
- public:
-
- fraccion (long num = 0, long den = 1) // constructor
- {
- numerador = num;
- denominador = den;
- simplificar (*this);
- }
-
- // operadores aritméticos binarios
-
- fraccion operator+ (fraccion frac)
- {
- long lmcm = mcm (denominador, frac.denominador);
- fraccion fr = fraccion (lmcm / denominador * numerador +
- lmcm / frac.denominador * frac.numerador, lmcm);
- simplificar (fr);
- return (fr);
- }
-
- fraccion operator- (fraccion frac)
- {
- return (operator+ (-frac));
- }
-
- fraccion operator* (fraccion frac)
- {
- fraccion fr = fraccion (numerador * frac.numerador,
- denominador * frac.denominador);
- simplificar (fr);
- return (fr);
- }
-
- fraccion operator/ (fraccion frac)
- {
- return (operator* (fraccion (frac.denominador, frac.numerador)));
- }
-
- // operadores de asignación binarios
-
- fraccion operator+= (fraccion frac)
- {
- return (*this = *this + frac);
- }
-
- fraccion operator-= (fraccion frac)
- {
- return (*this = *this - frac);
- }
-
- fraccion operator*= (fraccion frac)
- {
- return (*this = *this * frac);
- }
-
- fraccion operator/= (fraccion frac)
- {
- return (*this = *this / frac);
- }
-
- // operadores aritméticos unarios
-
- fraccion operator+ (void)
- {
- return (*this);
- }
-
- fraccion operator- (void)
- {
- return (fraccion (-numerador, denominador));
- }
-
- // operadores de asignación unarios
-
- fraccion operator++ (void)
- {
- return (*this += 1);
- }
-
- fraccion operator-- (void)
- {
- return (*this -= 1);
- }
-
- // otros operadores
-
- operator double ()
- {
- return ((double) numerador / denominador);
- }
-
- friend ostream& operator<< (ostream &out, fraccion frac)
- {
- return (frac.denominador == 1 ?
- out << frac.numerador :
- out << frac.numerador << '/' << frac.denominador);
- }
-
- friend istream& operator>> (istream &in, fraccion& frac)
- {
- return (in >> frac.numerador >> '/' >> frac.denominador);
- }
-
- private:
-
- void simplificar (fraccion& frac);
-
- long mcd (long num1, long num2);
-
- long mcm (long num1, long num2) // devuelve mínimo común múltiplo
- {
- return (num1 / mcd (num1, num2) * num2);
- }
- };
-
- // En el interior de esta clase no se puede llamar al constructor fraccion,
- // ya que se produciría un bucle infinito
- void fraccion::simplificar (fraccion& frac)
- {
- if (frac.numerador == 0)
- {
- frac.numerador = 0;
- frac.denominador = 1;
- }
- else
- {
- long lmcd = mcd (frac.numerador, frac.denominador);
- frac.numerador = frac.numerador / lmcd;
- frac.denominador = frac.denominador / lmcd;
- }
-
- if (frac.numerador < 0 && frac.denominador < 0)
- {
- frac.numerador = -frac.numerador;
- frac.denominador = -frac.denominador;
- }
- else if (frac.numerador < 0 || frac.denominador < 0)
- {
- frac.numerador = - abs (frac.numerador);
- frac.denominador = abs (frac.denominador);
- }
- }
-
- // Devuelve el máximo común divisor de dos números
- long fraccion::mcd (long num1, long num2)
- {
- num1 = abs (num1);
- num2 = abs (num2);
-
- while (num1 != num2)
- if (num1 > num2)
- num1 -= num2;
- else
- num2 -= num1;
-
- return (num1);
- }
-
- inline void imprimir_operacion (const char *operacion)
- {
- cout << "\n*** Ejecutando: " << operacion;
- }
-
- inline void imprimir_variables (fraccion x, fraccion y, double z)
- {
- cout << "\nx = " << x << "\ny = " << y << "\nz = " << z;
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE fraccion\n";
-
- cout << "\n*** Declarando: fraccion x = 4 / 2, y (3, 9); double z = -x;";
- fraccion x = 4 / 2, y (3, 9); double z = -x;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("z = x = --y - 2;");
- z = x = --y - 2;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("x = fraccion(1,3) - 5, y = fraccion(10,-5) + fraccion(1,5) * 3;");
- x = fraccion (1, 3) - 5, y = fraccion (10, -5) + fraccion (1, 5) * 3;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("z = x - (y == 5), z = long (z), x += x -= z, y = x / z;");
- z = x - (y == 5), z = long (z), x += x -= z, y = x / z;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("z *= (x == y) < (z != y), y /= x;");
- z *= (x == y) < (z != y), y /= x;
- imprimir_variables (x, y, z);
-
- imprimir_operacion ("cout << \"\\nIntroduce x en la forma n/d: \", cin >> x;");
- cout << "\nIntroduce x en la forma n/d: ", cin >> x;
- cout << "x = " << x;
-
- getch ();
- }
- ende
- begine " PROGRAMA COPIAR "
- /*
- Este programa copia un fichero en otro. El fichero fuente debe existir, en
- caso de no ser así, se produce un error en la apertura de este fichero. Si
- el fichero destino no existe, se crea uno nuevo si es posible, si por el
- contrario ya existe, se sobreescribirá, es decir, se perderá la información
- que contega.
-
- Se ofrecen dos versiones. La segunda versión, que es la que se ejecuta,
- se suministra para poder ejecutar este programa desde el tutor. La segunda
- versión, que es la que está dentro del comentario, se suministra por si el
- usuario desea copiar este ejemplo a un fichero (se recomienda llamarlo
- COPIAR para que el nombre del programa ejecutable sea COPIAR) y convertirlo
- en un programa ejecutable; en esta forma es más útil leyendo los nombres de
- los ficheros desde la línea de órdenes del sistema operativo; la sintaxis
- es: COPIAR fichero_fuente fichero_destino.
- */
-
- #include <iostream.h> // para cerr, cout
- #include <stdlib.h> // para exit ()
- #include <fstream.h> // para ifstream, ofstream
-
- /*
- void main (int argc, char* argv[])
- {
- if (argc != 3)
- {
- cerr << "USO: COPIAR fichero1 fichero2\n";
- exit (-1);
- }
-
- ifstream fuente;
- ofstream destino;
-
- fuente.open (argv[1]);
- if (! fuente)
- {
- cerr << "No se puede abrir el fichero fuente " << argv[1]
- << " para lectura.\n";
- exit (-1);
- }
-
- destino.open (argv[2]);
- if (! destino)
- {
- cerr << "No se puede abrir el fichero destino " << argv[2]
- << " para escritura.\n";
- exit (-1);
- }
-
- char ch;
-
- while (destino && fuente.get (ch))
- destino.put (ch);
-
- cout << "Copia completada.\n";
-
- fuente.close ();
- destino.close ();
- }
- */
-
- void main (void)
- {
- cout << "\nCOPIAR fichero_fuente en fichero_destino.\n";
-
- const int longitud_maxima_fichero = 128;
- typedef char nombre_fichero [longitud_maxima_fichero];
- nombre_fichero nombre_fichero_fuente, nombre_fichero_destino;
-
- cout << "Introduce fichero fuente: ";
- cin.getline (nombre_fichero_fuente, longitud_maxima_fichero);
- cout << "Introduce fichero destino: ";
- cin.getline (nombre_fichero_destino, longitud_maxima_fichero);
-
- ifstream fuente;
- ofstream destino;
-
- fuente.open (nombre_fichero_fuente);
- if (! fuente)
- {
- cerr << "No se puede abrir el fichero fuente " << nombre_fichero_fuente
- << " para lectura.\n";
- exit (-1);
- }
-
- destino.open (nombre_fichero_destino);
- if (! destino)
- {
- cerr << "No se puede abrir el fichero destino " << nombre_fichero_destino
- << " para escritura.\n";
- exit (-1);
- }
-
- char ch;
-
- while (destino && fuente.get (ch))
- destino.put (ch);
-
- cout << "Copia completada.\n";
-
- fuente.close ();
- destino.close ();
- }
- ende
- begine " CLASE string "
- /*
- Este programa implementa la clase string y la función main para probarla.
- Esta clase cuenta las referencias a una cadena de caracteres para minimizar
- la copia y el espacio utilizado. La copia de clases es muy utilizada en
- objetos temporales tales como argumentos por valor u objetos devueltos por
- funciones.
- */
-
- #include <iostream.h> // cout, cin, cerr
- #include <conio.h> // getch ()
- #include <string.h> // strlen (), strcpy ()
- #include <stdlib.h> // exit ()
-
- class string
- {
- struct sstring
- {
- char *s; // puntero a los datos
- int n; // contador de referencias
- };
-
- sstring *p;
-
- public:
-
- string (char *); // string x = "abc"
- string (void); // string x;
- string (string &); // string x = string ...
- string& operator= (char *);
- string& operator= (string &);
- ~string ();
- char& operator[] (int i);
-
- friend ostream& operator<< (ostream&, string&);
- friend istream& operator>> (istream&, string&);
-
- friend int operator== (string &x, char *s)
- { return strcmp (x.p->s, s) == 0; }
-
- friend int operator== (string &x, string &y)
- { return strcmp (x.p->s, y.p->s) == 0; }
-
- friend int operator!= (string &x, char *s)
- { return strcmp (x.p->s, s) != 0; }
-
- friend int operator!= (string &x, string &y)
- { return strcmp (x.p->s, y.p->s) != 0; }
- };
-
- string::string (void)
- {
- p = new sstring;
- p->s = 0;
- p->n = 1;
- }
-
- string::string (char *s)
- {
- p = new sstring;
- p->s = new char [strlen (s) + 1];
- strcpy (p->s, s);
- p->n = 1;
- }
-
- string::string (string& x)
- {
- x.p->n++;
- p = x.p;
- }
-
- string::~string ()
- {
- if (--p->n == 0)
- {
- delete p->s;
- delete p;
- }
- }
-
- string& string::operator= (char *s)
- {
- if (p->n > 1) // se desconecta
- {
- p->n--;
- p = new sstring;
- }
- else if (p->n == 1)
- delete p->s;
-
- p->s = new char [strlen (s) + 1];
- strcpy (p->s, s);
- p->n = 1;
- return *this;
- }
-
- string& string::operator= (string& x)
- {
- x.p->n++;
- if (--p->n == 0)
- {
- delete p->s;
- delete p;
- }
- p = x.p;
- return *this;
- }
-
- ostream& operator<< (ostream& s, string& x)
- {
- return s << x.p->s;
- }
-
- istream& operator>> (istream& s, string& x)
- {
- const int tam = 256;
- char buf[tam];
- s.getline (buf, 256);
- x = buf;
- return s;
- }
-
- void error_en_string (char *p)
- {
- cerr << "\nError: " << p << "\n";
- getch ();
- exit (1);
- }
-
- char& string::operator[] (int i)
- {
- if (i < 0 || strlen (p->s) < i)
- error_en_string ("índice fuera de rango");
- return p->s[i];
- }
-
- void main (void)
- {
- cout << "EJEMPLO DE LA CLASE string\n";
-
- cout << "\nDeclarando: string s1, s2, s3;\n";
- string s1, s2, s3;
-
- cout << "\nIntroduce s1: ";
- cin >> s1;
-
- cout << "\nIntroduce s2: ";
- cin >> s2;
-
- cout << "\nAsignando: s3 = s1; s3: " << (s3 = s1) << "\n";
-
- cout << "\nComparando: s1 != s2: " << (s1 != s2) << "\n";
- cout << "\nComparando: s1 == s3: " << (s1 == s3) << "\n";
-
- cout << "\nIndexando: s2[5]: " << s2[5] << "\n";
-
- getch ();
- }
- ende
- begine " CONTADOR DE PALABRAS "
- /*
- Este programa cuenta el número de palabras contenidas en un fichero.
-
- Se ofrecen dos versiones. La segunda versión, que es la que se ejecuta,
- se suministra para poder ejecutar este programa desde el tutor. La segunda
- versión, que es la que está dentro del comentario, se suministra por si el
- usuario desea copiar este ejemplo a un fichero y convertirlo en un programa
- ejecutable; en esta forma es más útil leyendo el nombre del fichero desde
- la línea de órdenes del sistema operativo.
-
- En ambos casos, si se introduce como nombre de fichero el nombre CON, ya
- sea en minúsculas o en mayúsculas, lee de consola, esto es, de teclado.
- */
-
-
- #include <iostream.h> // cerr, cout
- #include <fstream.h> // ifstream
- #include <stdlib.h> // exit ()
- #include <ctype.h> // isspace ()
-
- /*
- void main (int argc, char *argv[])
- {
- if (argc != 2)
- {
- cerr << "USO: nombre_programa nombre_fichero\n";
- exit (-1);
- }
-
- ifstream fich (argv[1]);
- if (! fich)
- {
- cerr << "Error al intentar abrir el fichero " << argv[1] << "\n";
- exit (-1);
- }
-
- int cont_palabras = 0;
- const int longmaxpal = 256;
- char palabra[longmaxpal];
-
- do
- {
- fich >> palabra;
- if (*palabra) // if necesario por si el fichero no contiene ninguna palabra
- ++cont_palabras;
- } while (fich.good ());
-
- cout << "En el fichero " << argv[1] << " hay " << cont_palabras
- << " palabra" << (cont_palabras == 1 ? "" : "s") << ".\n";
-
- fich.close ();
- }
- */
-
- void main (void)
- {
- cout << "CONTADOR DE PALABRAS DE UN FICHERO.\n";
-
- const int longmaxnomfich = 256;
- char nomfich [longmaxnomfich];
-
- cout << "Introduce nombre de fichero: ";
- cin >> nomfich;
-
- ifstream fich (nomfich);
- if (! fich)
- {
- cerr << "Error al intentar abrir el fichero " << nomfich << "\n";
- exit (-1);
- }
-
- int cont_palabras = 0;
- const int longmaxpal = 256;
- char palabra[longmaxpal];
-
- do
- {
- fich >> palabra;
- if (*palabra) // if necesario por si el fichero no contiene ninguna palabra
- ++cont_palabras;
- } while (fich.good ());
-
- cout << "En el fichero " << nomfich << " hay " << cont_palabras
- << " palabra" << (cont_palabras == 1 ? "" : "s") << ".\n";
-
- fich.close ();
- }
- ende
- end
-